/**
 * portal - jQuery EasyUI
 * 
 * Licensed under the GPL: http://www.gnu.org/licenses/gpl.txt
 * 
 * Copyright 2010-2012 stworthy [ stworthy@gmail.com ]
 * 
 * Dependencies: draggable panel
 * 
 */
(function($) {
	/**
	 * initialize the portal
	 */
	function init(target) {
		$(target).addClass('portal');
		var table = $(
				'<table border="0" cellspacing="0" cellpadding="0"><tr></tr></table>')
				.appendTo(target);
		var tr = table.find('tr');

		var columnWidths = [];
		var totalWidth = 0;
		$(target).children('div:first').addClass('portal-column-left');
		$(target).children('div:last').addClass('portal-column-right');
		$(target).find('>div').each(function() { // each column panel
			var column = $(this);
			totalWidth += column.outerWidth();
			columnWidths.push(column.outerWidth());

			var td = $('<td class="portal-column-td"></td>').appendTo(tr);
			column.addClass('portal-column').appendTo(td);
			column.find('>div').each(function() { // each portal panel
				var p = $(this).addClass('portal-p').panel({
					doSize : false,
					cls : 'portal-panel'
				});
				makeDraggable(target, p);
			});
		});
		for (var i = 0; i < columnWidths.length; i++) {
			columnWidths[i] /= totalWidth;
		}

		$(target).bind('_resize', function() {
			var opts = $.data(target, 'portal').options;
			if (opts.fit == true) {
				setSize(target);
			}
			return false;
		});

		return columnWidths;
	}

	function setSize(target) {
		var t = $(target);
		var opts = $.data(target, 'portal').options;
		if (opts.fit) {
			var p = t.parent();
			opts.width = p.width();
			opts.height = p.height();
		}
		if (!isNaN(opts.width)) {
			t._outerWidth(opts.width);
		} else {
			t.width('auto');
		}
		if (!isNaN(opts.height)) {
			t._outerHeight(opts.height);
		} else {
			t.height('auto');
		}

		var hasScroll = t.find('>table').outerHeight() > t.height();
		var width = t.width();
		var columnWidths = $.data(target, 'portal').columnWidths;
		var leftWidth = 0;

		// calculate and set every column size
		for (var i = 0; i < columnWidths.length; i++) {
			var p = t.find('div.portal-column:eq(' + i + ')');
			var w = Math.floor(width * columnWidths[i]);
			if (i == columnWidths.length - 1) {
				// w = width - leftWidth - (hasScroll == true ? 28 : 10);
				w = width - leftWidth - (hasScroll == true ? 18 : 0);
			}
			p._outerWidth(w);
			leftWidth += p.outerWidth();

			// resize every panel of the column
			p.find('div.portal-p').panel('resize', {
				width : p.width()
			});
		}
		opts.onResize.call(target, opts.width, opts.height);
	}

	/**
	 * set draggable feature for the specified panel
	 */
	function makeDraggable(target, panel) {
		var spacer;
		panel
				.panel('panel')
				.draggable(
						{
							handle : '>div.panel-header>div.panel-title',
							proxy : function(source) {
								var p = $(
										'<div class="portal-proxy">proxy</div>')
										.insertAfter(source);
								p.width($(source).width());
								p.height($(source).height());
								p.html($(source).html());
								p.find('div.portal-p').removeClass('portal-p');
								return p;
							},
							onBeforeDrag : function(e) {
								var pbody = $(this).find(".panel-body");
								var _wrap = $("<div id='movewrap_' class='portalmovewrap'></div>");
								pbody.append(_wrap);
								e.data.startTop = $(this).position().top
										+ $(target).scrollTop();
							},
							onStartDrag : function(e) {
								$(this).hide();
								spacer = $('<div class="portal-spacer"></div>')
										.insertAfter(this);
								setSpacerSize($(this).outerWidth(), $(this)
										.outerHeight());
							},
							onDrag : function(e) {
								var p = findPanel(e, this);
								if (p) {
									if (p.pos == 'up') {
										spacer.insertBefore(p.target);
									} else {
										spacer.insertAfter(p.target);
									}
									setSpacerSize($(p.target).outerWidth());
								} else {
									var c = findColumn(e);
									if (c) {
										if (c.find('div.portal-spacer').length == 0) {
											spacer.appendTo(c);
											setSize(target);
											setSpacerSize(c.width());
										}
									}
								}
							},
							onStopDrag : function(e) {
								$(this).css('position', 'static');
								$(this).show();
								spacer.hide();
								$(this).insertAfter(spacer);
								spacer.remove();
								setSize(target);
								panel.panel('move');
								$("#movewrap_").remove();
								var nidx = this.parentNode.parentNode.cellIndex;
								panel.panel("options").columnIndex = nidx;
								var opts = $.data(target, 'portal').options;
								opts.onStateChange.call(target);
							}
						});

		/**
		 * find which panel the cursor is over
		 */
		function findPanel(e, source) {
			var result = null;
			$(target).find('div.portal-p').each(
					function() {
						var pal = $(this).panel('panel');
						if (pal[0] != source) {
							var pos = pal.offset();
							if (e.pageX > pos.left
									&& e.pageX < pos.left + pal.outerWidth()
									&& e.pageY > pos.top
									&& e.pageY < pos.top + pal.outerHeight()) {
								if (e.pageY > pos.top + pal.outerHeight() / 2) {
									result = {
										target : pal,
										pos : 'down'
									};
								} else {
									result = {
										target : pal,
										pos : 'up'
									};
								}
							}
						}
					});
			return result;
		}

		/**
		 * find which portal column the cursor is over
		 */
		function findColumn(e) {
			var result = null;
			$(target).find('div.portal-column').each(
					function() {
						var pal = $(this);
						var pos = pal.offset();
						if (e.pageX > pos.left
								&& e.pageX < pos.left + pal.outerWidth()) {
							result = pal;
						}
					});
			return result;
		}

		/**
		 * set the spacer size
		 */
		function setSpacerSize(width, height) {
			spacer._outerWidth(width);
			if (height) {
				spacer._outerHeight(height);
			}
		}
	}

	$.fn.portal = function(options, param) {
		if (typeof options == 'string') {
			return $.fn.portal.methods[options](this, param);
		}

		options = options || {};
		return this.each(function() {
			var state = $.data(this, 'portal');
			if (state) {
				$.extend(state.options, options);
			} else {
				state = $.data(this, 'portal', {
					options : $.extend({}, $.fn.portal.defaults, $.fn.portal
							.parseOptions(this), options),
					columnWidths : init(this)
				});
			}
			if (state.options.border) {
				$(this).removeClass('portal-noborder');
			} else {
				$(this).addClass('portal-noborder');
			}
			setSize(this);
		});
	};

	$.fn.portal.methods = {
		options : function(jq) {
			return $.data(jq[0], 'portal').options;
		},
		resize : function(jq, param) {
			return jq.each(function() {
				if (param) {
					var opts = $.data(this, 'portal').options;
					if (param.width)
						opts.width = param.width;
					if (param.height)
						opts.height = param.height;
				}
				setSize(this);
			});
		},
		getPanels : function(jq, columnIndex) {
			var c = jq; // the panel container
			if (columnIndex >= 0) {
				c = jq.find('div.portal-column:eq(' + columnIndex + ')');
			}
			var panels = [];
			c.find('div.portal-p').each(function() {
				panels.push($(this));
			});
			return panels;
		},
		add : function(jq, param) { // param: {panel,columnIndex}
			return jq.each(function() {
				var c = $(this).find(
						'div.portal-column:eq(' + param.columnIndex + ')');
				var p = param.panel.addClass('portal-p');
				p.panel('panel').addClass('portal-panel').appendTo(c);
				makeDraggable(this, p);
				p.panel('resize', {
					width : c.width()
				});
			});
		},
		remove : function(jq, panel) {
			return jq.each(function() {
				var panels = $(this).portal('getPanels');
				for (var i = 0; i < panels.length; i++) {
					var p = panels[i];
					if (p[0] == $(panel)[0]) {
						p.panel('destroy');
					}
				}
			});
		},
		disableDragging : function(jq, panel) {
			panel.panel('panel').draggable('disable');
			return jq;
		},
		enableDragging : function(jq, panel) {
			panel.panel('panel').draggable('enable');
			return jq;
		}
	};

	$.fn.portal.parseOptions = function(target) {
		var t = $(target);
		return {
			width : (parseInt(target.style.width) || undefined),
			height : (parseInt(target.style.height) || undefined),
			border : (t.attr('border') ? t.attr('border') == 'true' : undefined),
			fit : (t.attr('fit') ? t.attr('fit') == 'true' : undefined)
		};
	};

	$.fn.portal.defaults = {
		width : 'auto',
		height : 'auto',
		border : true,
		fit : false,
		onResize : function(width, height) {
		},
		onStateChange : function() {
		}
	};
})(jQuery);